﻿using System;
using System.Collections.Generic;
using System.Linq;
using Busconeitor.Domain.Entities;
using Busconeitor.Domain.Repositories;

namespace Busconeitor.DataLayer.MockRepository
{
    public class MemoryRepository<T> : IRepository<T> where T : BaseEntity
    {
        IDictionary<Type, IDictionary<object, T>> _dictionary;

        IDictionary<Type, IDictionary<object, T>> Dictionary
        {
            get
            {
                if (_dictionary == null)
                    _dictionary = new Dictionary<Type, IDictionary<object, T>>();

                return _dictionary;
            }
        }

        #region Implementation of IRepository<T>

        public T GetOne(object id)
        {
            if (Dictionary.ContainsKey(typeof(T)) && Dictionary[typeof(T)].ContainsKey(id))
                return Dictionary[typeof(T)][id];

            return default(T);
        }

        public long Count()
        {
            return GetAll().Count();
        }

        public IEnumerable<T> GetAll()
        {
            IList<T> all = new List<T>();

            if (Dictionary.ContainsKey(typeof(T)))
            {
                foreach (T t in Dictionary[typeof(T)].Values)
                {
                    all.Add(t);
                }
            }
            return all;
        }

        public void Add(T entity)
        {
            if (!Dictionary.ContainsKey(typeof(T)))
                Dictionary[typeof(T)] = new Dictionary<object, T>();

            // uso reflection para setear el id porque el setter no es publico
            entity.GetType().BaseType.GetProperty("Id").SetValue(entity, Dictionary[typeof(T)].Count + 1, null);

            Dictionary[typeof(T)].Add(entity.Id, entity);
        }

        public void Update(T entity)
        {
            if (Dictionary.ContainsKey(typeof(T)) && Dictionary[typeof(T)].ContainsKey(entity.Id))
                Dictionary[typeof(T)][entity.Id] = entity;
        }

        public void Delete(T entity)
        {
            if (Dictionary.ContainsKey(typeof(T)) && Dictionary[typeof(T)].ContainsKey(entity.Id))
                Dictionary[typeof(T)].Remove(entity.Id);
        }

        public IEnumerable<T> GetSlice(int slice, int quantity, string order, bool ascending)
        {
            if (!Dictionary.ContainsKey(typeof(T)))
                return new List<T>();

            return Dictionary[typeof(T)].Values.ToList().GetRange(slice, quantity);
        }

        #endregion
    }
}
